#include <iostream>
using namespace std;



#include "HookProc\HookProcManager.h"
#include "HookProc/logger.h"



#include <boost/bind.hpp> 

#include <Windows.h>



int consoleMsg( const char* Msg )
{
	std::cout << "consoleMsg: "<< Msg << std::endl;
	return 117;
}


int MB_TEST( sd::hp::Hook< decltype( MessageBox )> &hook, HWND hwnd, const char* text, const char* title, int type )
{
	cout << "Original " << hook.getName()  << " will be called"<<endl;
	int res =  hook.getOriginal()(hwnd,text,title,type);
	cout << "Original called secsesful"<<endl;

	return res;
}


int MB_TEST2( const std::string& text, const std::string& title, const std::string& add )
{
	std::cout << "MB_TEST2:"<< title <<":"<< text << "____"<<add<< std::endl;
	return 0;
}






volatile bool runThread = true;

DWORD  __stdcall threadProc(void*)
{
	cout << "start threadProc"<<endl;
	while(runThread)
	{
		Sleep(500);
		cout << "threadProc iteration" << endl;
	}

	return 0;
}




void Test2()
{
	using namespace sd::hp;
	{
		auto& hook  = SD_HP_CREATE_HOOK( MessageBoxA, "user32.dll" );

		hook.setActive(true);

		hook.setCallback( boost::bind( consoleMsg, _3 ) );
		MessageBoxA( 0, "TestText2.1", "TestTitle2.1", 0 );
		std::cout << "-------------------------------------------------" << std::endl;

		hook.setCallback( boost::bind( MB_TEST2, _2, _3, "Additional TExt" ) );
		MessageBoxA( 0, "TestText2.2", "TestTitle2.2", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		hook.setCallback(  boost::bind( hook.getOriginal(), _1, _2, _3, _4  ) );
		MessageBoxA( 0, "TestText2.3", "TestTitle2.3", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		hook.setCallback( hook.getOriginal() );
		MessageBoxA( 0, "TestText2.4", "TestTitle2.4", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		hook.setCallback(  boost::bind( MB_TEST, boost::ref(hook), _1, _2, _3, _4  ) );
		MessageBoxA( 0, "TestText2.5", "TestTitle2.5", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		hook.setActive(false);
		MessageBoxA( 0, "TestText2.6", "TestTitle2.6", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		hook.setActive(true);
		MessageBoxA( 0, "TestText2.7", "TestTitle2.7", 0 );
		std::cout << "-------------------------------------------------" << std::endl;


		sd::tools::logger::logManager::getInstance().init( std::wcout );

		hook.setCallbackSynth( sd::tools::logger::makeLogger( hook ) );

		MessageBoxA( 0, "TestText2.8.1", "TestTitle2.8.1", 0 );
		MessageBoxA( 0, "TestText2.8.2", "TestTitle2.8.2", 0 );
		MessageBoxA( 0, "TestText2.8.3", "TestTitle2.8.3", 0 );
		


	}
};





void Test3()
{
	using namespace sd::hp;
	using namespace sd::tools::logger;

	sd::tools::logger::logManager::getInstance().init( std::wcout );

	{

		auto& hook = SD_HP_CREATE_HOOK( CreateWindowExA, "user32.dll" );

		hook.setActive(true);
		hook.setCallbackSynth( sd::tools::logger::makeLogger( hook ) );


		::CreateWindowExA(0,"BUTTON",0,0,0,0,0,0,NULL,NULL,NULL,NULL);
	}

	{

		auto& hook = SD_HP_CREATE_HOOK( CreateWindowExW, "user32.dll" );

		hook.setActive(true);
		hook.setCallbackSynth( sd::tools::logger::makeLogger( hook ) );


		::CreateWindowExW(0,L"BUTTON",L"btn",0,0,0,0,0,NULL,NULL,NULL,NULL);
	}


}



int main (int /*argc*/, char ** /*argv[]*/)
{

	__try
	{
		cout << "Start ProcHook Test" << endl;
		cout << "Start Test2 - hooking windows API" << endl;
		Test2();
		cout << "Start Test3 - automatic api logger" << endl;
		Test3();
		cout << "All tests completed" << endl;
	}__except(1)
	{
		cout << "Ou crap - " << GetLastError() <<endl;
	}

	cin.get();

	return(0);
}


